package yui.comn.mybatisx.extension.mgr;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.metadata.IPage;

import yui.comn.mybatisx.core.conditions.Wrapper;
import yui.comn.mybatisx.core.mapper.BaseDao;
import yui.comn.mybatisx.core.toolkit.EntityUtils;
import yui.comn.mybatisx.extension.node.TreeNode;

/**
 * <p>
 * 基础服务类
 * </p>
 *
 * @author yuyi (1060771195@qq.com)
 */
@SuppressWarnings("unchecked")
public interface IMgr<T, D> {

    
    /**
     * 默认批次提交数量
     */
    int DEFAULT_BATCH_SIZE = 1000;
    
    /**
     * <p>
     * 获取对应BaseDao
     * </p>
     * @return BaseDao
     */
    BaseDao<T, D> getBaseDao();
    
    /**
     * 获取 entity 的 class
     *
     * @return {@link Class<T>}
     */
    Class<T> getEntityClass();
    
    default <A> IPage<A> getPage(Wrapper<T> wrapper) {
        return EntityUtils.getPage(wrapper);
    }
    
    /**
     * <p>
     * 插入一条记录
     * </p>
     *
     * @param entity 实体对象
     */
    default T add(T entity) {
        getBaseDao().insert(entity);
        return entity;
    }
    
    /**
     * <p>
     * 插入（真正批量）
     * </p>
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default Collection<T> addBatch(Collection<T> entityList) {
        addBatch(entityList, DEFAULT_BATCH_SIZE);
        return entityList;
    }
    
    /**
     * <p>
     * 插入（真正批量）
     * </p>
     *
     * @param entityList 实体对象集合
     * @param batchSize  插入批次数量
     */
    Collection<T> addBatch(Collection<T> entityList, int batchSize);
    
    /**
     * <p>
     * 批量修改插入
     * </p>
     *
     * @param entityList 实体对象集合
     */
    default T addOrUpdate(T entity) {
        List<T> entityList = new ArrayList<>();
        entityList.add(entity);
        addOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
        return entity;
    }
    
    /**
     * <p>
     * 批量修改插入
     * </p>
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default Collection<T> addOrUpdateBatch(Collection<T> entityList) {
        addOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
        return entityList;
    }

    /**
     * <p>
     * 批量修改插入
     * </p>
     *
     * @param entityList 实体对象集合
     * @param batchSize  每次的数量
     */
    Collection<T> addOrUpdateBatch(Collection<T> entityList, int batchSize);
    
    /**
     * <p>
     * 根据ID 批量更新
     * </p>
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default Collection<T> updateBatchById(Collection<T> entityList) {
        updateBatchById(entityList, DEFAULT_BATCH_SIZE);
        return entityList;
    }

    /**
     * <p>
     * 根据ID 批量更新
     * </p>
     *
     * @param entityList 实体对象集合
     * @param batchSize  更新批次数量
     */
    Collection<T> updateBatchById(Collection<T> entityList, int batchSize);
    
    /**
     * <p>
     * 根据ID 批量更新
     * </p>
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default Collection<D> updateBatchByDtoId(Collection<D> entityList) {
        updateBatchByDtoId(entityList, DEFAULT_BATCH_SIZE);
        return entityList;
    }
    
    /**
     * <p>
     * 根据ID 批量更新
     * </p>
     *
     * @param entityList 实体对象集合
     * @param batchSize  更新批次数量
     */
    Collection<D> updateBatchByDtoId(Collection<D> entityList, int batchSize);
    
    /**
     * <p>
     * 根据ID 批量更新所有值
     * </p>
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default Collection<T> updateAllBatchById(Collection<T> entityList) {
        updateBatchById(entityList, DEFAULT_BATCH_SIZE);
        return entityList;
    }

    /**
     * <p>
     * 根据ID 批量更新所有值
     * </p>
     *
     * @param entityList 实体对象集合
     * @param batchSize  更新批次数量
     */
    Collection<T> updateAllBatchById(Collection<T> entityList, int batchSize);
    
    /**
     * <p>
     * 根据ID 批量更新所有值
     * </p>
     *
     * @param entityList 实体对象集合
     * @param batchSize  更新批次数量
     */
    Collection<D> updateAllBatchByDtoId(Collection<D> entityList, int batchSize);
    
    /**
     * <p>
     * 根据ID 批量更新所有值
     * </p>
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default Collection<D> updateAllBatchByDtoId(Collection<D> entityList) {
        updateBatchByDtoId(entityList, DEFAULT_BATCH_SIZE);
        return entityList;
    }
    
    /**
     * <p>
     * 根据 ID 修改全部的
     * </p>
     *
     * @param entity 实体对象
     */
    int update(T entity, Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 ID 修改有值的
     * </p>
     *
     * @param entity 实体对象
     */
    int update(T entity);
    
    /**
     * <p>
     * 根据 ID 修改所有
     * </p>
     *
     * @param entity 实体对象
     */
    int updateAll(T entity);
    
    /**
     * 根据 entity 强制删除记录
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null,里面的 entity 用于生成 where 语句）
     */
    int defunct(Wrapper<T> wrapper);
    
    /**
     * 根据 entity 条件，删除记录
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null,里面的 entity 用于生成 where 语句）
     */
    int delete(Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 ID 删除
     * </p>
     *
     * @param id 主键ID
     */
    int deleteById(Serializable id);
    
    /**
     * <p>
     * 删除（根据ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     * @param batchSize  删除批次数量
     */
    int deleteByIds(Collection<? extends Serializable> idList, int batchSize);
    /**
     * <p>
     * 删除（根据ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    @Transactional(rollbackFor = Exception.class)
    default int deleteByIds(Collection<? extends Serializable> idList) {
        return deleteByIds(idList, DEFAULT_BATCH_SIZE);
    }
    
    /**
     * <p>
     * 删除（根据对象ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     * @param batchSize  删除批次数量
     */
    @Transactional(rollbackFor = Exception.class)
    default int deleteBatchVoIds(Collection<T> entityList, int batchSize) {
        return deleteByIds(EntityUtils.listPrimaryKeyValueByVos(entityList), batchSize);
    }
    
    /**
     * <p>
     * 删除（根据对象ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    @Transactional(rollbackFor = Exception.class)
    default int deleteBatchVoIds(Collection<T> entityList) {
        return deleteBatchVoIds(entityList, DEFAULT_BATCH_SIZE);
    }
    
    /**
     * <p>
     * 删除（根据对象ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     * @param batchSize  删除批次数量
     */
    @Transactional(rollbackFor = Exception.class)
    default int deleteBatchDtoIds(Collection<D> entityList, int batchSize) {
        return deleteBatchVoIds((Collection<T>) EntityUtils.listVo(entityList), batchSize);
    }
    
    /**
     * <p>
     * 删除（根据对象ID 批量删除）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     * @param batchSize  删除批次数量
     */
    @Transactional(rollbackFor = Exception.class)
    default int deleteBatchDtoIds(Collection<D> entityList) {
        return deleteBatchDtoIds(entityList, DEFAULT_BATCH_SIZE);
    }
    
    /**
     * <p>
     * 删除（根据ID 删除树形结构数据）
     * </p>
     *
     * @param id 主键ID
     * @param pidColumn 父节点主键
     */
    void deleteTreeById(Serializable id, String pidColumn);
    
    /**
     * <p>
     * 删除（根据ID 批量删除树形结构数据）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     * @param pidColumn 父节点主键
     */
    @Transactional(rollbackFor = Exception.class)
    default void deleteTreeByIds(Collection<? extends Serializable> idList, String pidColumn) {
        for (Serializable id : idList) {
            deleteTreeById(id, pidColumn);
        }
    }
    
    /**
     * <p>
     * 查询树形结构列表
     * </p>
     * @param wrapper 实体对象封装操作类（可以为 null）
     * @param treeNodeClass 返回树形结构类型
     * @return
     */
    default <N extends TreeNode<N>> List<N> listTreeNode(Wrapper<T> wrapper, Class<N> treeNodeClass) {
    	return listTreeNode(wrapper, treeNodeClass, null);
    }
    
    /**
     * <p>
     * 查询树形结构列表
     * </p>
     * @param wrapper 实体对象封装操作类（可以为 null）
     * @param treeNodeClass 返回树形结构类型
     * @return
     */
    <N extends TreeNode<N>> List<N> listTreeNode(Wrapper<T> wrapper, Class<N> treeNodeClass, Long pid);
    
    /**
     * <p>
     * 根据 ID 查询
     * </p>
     *
     * @param id 主键ID
     */
    D getById(Serializable id);
    
    /**
     * <p>
     * 根据 ID 查询
     * </p>
     *
     * @param id 主键ID
     */
    default T getVoById(Serializable id) {
        return (T) EntityUtils.getVo(getById(id));
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询一条记录
     * </p>
     *
     * @param wrapper 实体对象
     */
    default D get(Wrapper<T> wrapper) {
        return get(wrapper, true);
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询一条记录
     * </p>
     *
     * @param wrapper 实体对象
     */
    default T getVo(Wrapper<T> wrapper) {
        return (T) EntityUtils.getVo(get(wrapper));
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询一条记录
     * </p>
     *
     * @param wrapper 实体对象
     */
    D get(Wrapper<T> wrapper, boolean throwEx);
    
    /**
     * <p>
     * 根据 entity 条件，查询一条记录
     * </p>
     *
     * @param wrapper 实体对象
     */
    default T getVo(Wrapper<T> wrapper, boolean throwEx) {
        return (T) EntityUtils.getVo(get(wrapper, throwEx));
    }
    
    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    D getByMap(Map<String, Object> columnMap);
    
    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    default T getVoByMap(Map<String, Object> columnMap) {
        return (T) EntityUtils.getVo(getByMap(columnMap));
    }
    
    /**
     * <p>
     * 根据字段条件，查询一条记录
     * </p>
     *
     * @param entity 实体对象
     */
    D get(String colomns, Object... values);
    
    /**
     * <p>
     * 根据字段条件，查询一条记录
     * </p>
     *
     * @param colomns 多个列逗号隔开
     * @param value 多个值对应多个colomn
     */
    default T getVo(String colomns, Object... values) {
        return (T) EntityUtils.getVo(get(colomns, values));    
    }
    
    /**
     * <p>
     * 根据 Wrapper 条件，查询总记录数
     * </p>
     *
     * @param wrapper 实体对象
     */
    Integer count(Wrapper<T> wrapper);
    
    /**
     * <p>
     * 查询全部记录
     * </p>
     */
    default List<D> list() {
        return list(null);
    }
    
    /**
     * <p>
     * 查询全部记录
     * </p>
     */
    default List<T> listVo() {
        return (List<T>) EntityUtils.listVo(list());
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    List<D> list(Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    default List<T> listVo(Wrapper<T> wrapper) {
        return (List<T>) EntityUtils.listVo(list(wrapper));
    }
    
    /**
     * <p>
     * 查询（根据ID 批量查询）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    List<D> listByIds(Collection<? extends Serializable> idList);
    
    /**
     * <p>
     * 查询（根据ID 批量查询）
     * </p>
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    default List<T> listVoByIds(Collection<? extends Serializable> idList) {
        return (List<T>) EntityUtils.listVo(listByIds(idList));
    }

    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    List<D> listByMap(Map<String, Object> columnMap);
    
    /**
     * <p>
     * 查询（根据 columnMap 条件）
     * </p>
     *
     * @param columnMap 表字段 map 对象
     */
    default List<T> listVoByMap(Map<String, Object> columnMap) {
        return (List<T>) EntityUtils.listVo(listByMap(columnMap));
    }

    /**
     * <p>
     * 根据字段条件，查询全部记录
     * </p>
     *
     * @param entityList 实体对象集合
     */
    default List<D> list(String colomns, Object... values) {
        return listByMap(EntityUtils.getMap(colomns, values));
    }
    
    /**
     * <p>
     * 根据字段条件，查询全部记录
     * </p>
     *
     * @param entityList 实体对象集合
     */
    default List<T> listVo(String colomns, Object... values) {
        return (List<T>) EntityUtils.listVo(list(colomns, values));
    }
    
    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    List<Map<String, Object>> listMaps(Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 columnMap 条件，查询全部记录
     * </p>
     *
     *@param columnMap 表字段 map 对象
     */
    List<Map<String, Object>> listMapsByMap(Map<String, Object> columnMap);

    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录
     * 注意： 只返回第一个字段的值
     * </p>
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    List<Object> listObjs(Wrapper<T> wrapper);

    /**
     * <p>
     * 根据 entity 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param wrapper.page         分页查询条件（可以为 RowBounds.DEFAULT）
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    default <E extends IPage<D>> E page(Wrapper<T> wrapper) {
        return (E) page(getPage(wrapper), wrapper);
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件（可以为 RowBounds.DEFAULT）
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    <E extends IPage<D>> E page(E page, Wrapper<T> wrapper);
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件（可以为 RowBounds.DEFAULT）
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    default <E extends IPage<T>> E pageVo(Wrapper<T> wrapper) {
        return (E) EntityUtils.pageVo(page(wrapper));
    }
    
    /**
     * <p>
     * 根据 entity 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件（可以为 RowBounds.DEFAULT）
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    default <E extends IPage<T>> E pageVo(IPage<D> page, Wrapper<T> wrapper) {
        return (E) EntityUtils.pageVo(page(page, wrapper));
    }

    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param wrapper.page         分页查询条件
     * @param wrapper 实体对象封装操作类
     */
    default IPage<Map<String, Object>> pageMaps(Wrapper<T> wrapper) {
        return pageMaps(getPage(wrapper), wrapper);
    }
    
    /**
     * <p>
     * 根据 Wrapper 条件，查询全部记录（并翻页）
     * </p>
     *
     * @param page         分页查询条件
     * @param wrapper 实体对象封装操作类
     */
    <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> wrapper);
    
    /*****************************************mybaits plus 原始批量操作*****************************************/
    /**
     * 插入（批量）
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean addBatchOrig(Collection<T> entityList) {
        return addBatchOrig(entityList, DEFAULT_BATCH_SIZE);
    }
    
    /**
     * 插入（批量）
     *
     * @param entityList 实体对象集合
     * @param batchSize  插入批次数量
     */
    boolean addBatchOrig(Collection<T> entityList, int batchSize);
    
    /**
     * 批量修改插入
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean addOrUpdateBatchOrig(Collection<T> entityList) {
        return addOrUpdateBatchOrig(entityList, DEFAULT_BATCH_SIZE);
    }
    
    /**
     * 批量修改插入
     *
     * @param entityList 实体对象集合
     * @param batchSize  每次的数量
     */
    boolean addOrUpdateBatchOrig(Collection<T> entityList, int batchSize);
    
    /**
     * 根据ID 批量更新
     *
     * @param entityList 实体对象集合
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean updateBatchByIdOrig(Collection<T> entityList) {
        return updateBatchByIdOrig(entityList, DEFAULT_BATCH_SIZE);
    }
    
    /**
     * 根据ID 批量更新
     *
     * @param entityList 实体对象集合
     * @param batchSize  更新批次数量
     */
    boolean updateBatchByIdOrig(Collection<T> entityList, int batchSize);
    
}
